﻿using NHibernate;
using NHibernate.Linq;
using Laugh.Data.DatabaseCfg;
using System.Collections;
using System.Collections.Concurrent;
using System;
using System.Collections.Generic;
using NHibernate.Type;

namespace Laugh.Data
{
    public class SqlQuery : ISqlQuery
    {
        private string databaseKey = "default";
        private ISessionFactoryHolder _sessionFactoryHolder;
        ConcurrentDictionary<string, ISession> _sessions = new ConcurrentDictionary<string, ISession>(StringComparer.OrdinalIgnoreCase);

        public SqlQuery(ISessionFactoryHolder sessionFactoryHolder)
        {
            _sessionFactoryHolder = sessionFactoryHolder;
        }

        public ISqlQuery UseDatabase(string key)
        {
            databaseKey = key;
            return this;
        }

        public ITransaction BeginTransaction()
        {
            return new DataTransaction(Session);
        }

        public int UpdateOrDelete(string sql)
        {
            return Session.CreateSQLQuery(sql).ExecuteUpdate();
        }

        public IList Select(string sql)
        {
            ISQLQuery query = Session.CreateSQLQuery(sql);
            return query.List();
        }

        public IList<T> Select<T>(string sql) where T : new()
        {
            ISQLQuery query = Session.CreateSQLQuery(sql);
            return query.AddEntity(typeof(T)).List<T>();
        }

        public T SelectSingle<T>(string sql)
        {
            ISQLQuery query = Session.CreateSQLQuery(sql);
            return query.UniqueResult<T>();
        }

        private ISession Session
        {
            get
            {
                return _sessions.GetOrAdd(databaseKey, key => _sessionFactoryHolder.GetSessionFactory(key).OpenSession());
            }
        }

        public void Dispose()
        {
            if (_sessions.Count > 0)
                _sessions.ForEach(i =>
                {
                    i.Value.Flush();
                    i.Value.Close();
                    i.Value.Dispose();
                });

            _sessions = null;
        }
    }
}
